package com.arpa.wms.service.impl;

import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.constant.StrConsts;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.entity.*;
import com.arpa.wms.domain.enums.*;
import com.arpa.wms.domain.vo.PdaSwitchPageVO;
import com.arpa.wms.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.extern.log4j.Log4j2;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;

import static com.arpa.wms.domain.consts.NumConst.*;

/**
 * PDA处理拣货
 * @author liuxr
 * @date 2021年05月29日 11:22
 */
@Service
@Log4j2
public class PickingOrderPdaServiceImpl implements PickingOrderService {

    @Autowired
    private IPickingService iPickingService;
    @Autowired
    private IPickingItemService iPickingItemService;

    @Autowired
    private IPickingRegisterService iPickingRegisterService;

    @Autowired
    private IWmsTaskService iWmsTaskService;

    @Autowired
    private IContainerService iContainerService;
    @Autowired
    private IDeliveryDistributionService iDeliveryDistributionService;
    @Autowired
    private IDeliveryItemService iDeliveryItemService;
    @Autowired
    private IDeliveryService iDeliveryService;
    @Autowired
    private PickingConfirmationService pickingConfirmationService;

    @Resource
    public RedissonClient redissonClient;

    @Autowired
    public IOutboundService iOutboundService;


    @Autowired
    public OutCheckService outCheckService;

    @Autowired
    public WavePickingConfirmationService wavePickingConfirmationService;

    /**
     * 批量拣货登记
     *
     * @param pickingCode
     * @param pickingItemCode
     * @param unFinishRegisterCode
     * @param pickingQuantity
     * @param containerBarCode
     * @author liuxr
     * @date 2021/5/29 11:22
     */
    @Override
    public PdaSwitchPageVO batchRegister(String pickingCode, String pickingItemCode, String unFinishRegisterCode, BigDecimal pickingQuantity, String containerBarCode) {

        PdaSwitchPageVO pdaSwitchPageVO = pickingRegister(pickingCode,pickingItemCode,unFinishRegisterCode,pickingQuantity,containerBarCode,true);
        int finishItemFlag = updateItemStatus(pickingCode,pickingItemCode,unFinishRegisterCode,pdaSwitchPageVO);
        if (finishItemFlag > 0) {
            updateFinsh(pickingCode,pickingItemCode,pdaSwitchPageVO);
        }
        return pdaSwitchPageVO;
    }

    /**
     * 单条拣货登记
     *
     * @param pickingCode
     * @param pickingItemCode
     * @param unFinishRegisterCode
     * @param pickingQuantity
     * @param containerBarCode
     * @author liuxr
     * @date 2021/5/29 11:22
     */
    @Override
    public PdaSwitchPageVO singleRegister(String pickingCode, String pickingItemCode, String unFinishRegisterCode, BigDecimal pickingQuantity, String containerBarCode) {
        PdaSwitchPageVO pdaSwitchPageVO = pickingRegister(pickingCode,pickingItemCode,unFinishRegisterCode,pickingQuantity,containerBarCode,false);
        int finishItemFlag = updateItemStatus(pickingCode,pickingItemCode,unFinishRegisterCode,pdaSwitchPageVO);
        if (finishItemFlag > 0) {
            updateFinsh(pickingCode,pickingItemCode,pdaSwitchPageVO);
        }
        return pdaSwitchPageVO;
    }

    /**
     * 拣货登记
     * 1、数据校验
     * 2、更新数据
     *
     * @author liuxr
     * @date 2021/5/29 12:13
     * @param pickingCode 拣货单号
     * @param pickingItemCode 明细标识
     * @param unFinishRegisterCode 拣货登记标识
     * @param pickingQuantity 拣货数量
     * @param containerBarCode 容器号
     * @param isBatch 是否批量PickingItem
     */

    @Transactional(rollbackFor = Exception.class)
    public PdaSwitchPageVO pickingRegister(String pickingCode, String pickingItemCode, String unFinishRegisterCode, BigDecimal pickingQuantity, String containerBarCode,
                                 boolean isBatch){
        PdaSwitchPageVO switchPageVO = new PdaSwitchPageVO();
        // 默认PDA不跳转
        switchPageVO.setToPage(NumConst.NUM_ZERO);
        switchPageVO.setMsg("操作成功");

        // 判断明细是否已完成
        PickingItem item = iPickingItemService.getOne(new QueryWrapper<PickingItem>().lambda().eq(PickingItem::getCode, pickingItemCode).eq(PickingItem::getGroupCode,UserUtil.getBranchCode()));

        log.info("PDA批量拣货确认，获取拣货明细，{}",JSONUtil.toJsonStr(item));
        if (PickingRegisterStatusEnum.FINISH_PICKING.getValue().equals(item.getStatus())) {
            throw new ServiceException("已拣货完成，无法继续拣货");
        }
        String wavePickingCode = item.getWavePickingCode();
        String oldInventoryCode = item.getOldInventoryCode();
        String groupCode = item.getGroupCode();

        PickingRegister pickingRegister = iPickingRegisterService.getOne(new QueryWrapper<PickingRegister>().lambda()
                .eq(PickingRegister::getGroupCode,UserUtil.getBranchCode())
                .eq(PickingRegister::getCode, unFinishRegisterCode));
        pickingRegister.setPickingQuantity(pickingQuantity);
        pickingRegister.setContainerBarCode(containerBarCode);

        log.info("PDA批量拣货确认，获取拣货登记信息，{}",JSONUtil.toJsonStr(pickingRegister));
        // 更新任务状态
        iWmsTaskService.updateTaskWorkingBySourceCode(pickingCode);

        // 校验拣货数量
        if (pickingRegister.getPickingQuantity() == null || BigDecimal.ZERO.compareTo(pickingRegister.getPickingQuantity()) >= 0) {
            log.error("PDA批量拣货确认，拣货数量必须大于0，拣货数量: {}",pickingRegister.getPickingQuantity());
            throw new ServiceException("拣货数量必须大于0");
        }
        // 检查主单状态
        Picking picking = this.iPickingService.getOne(new QueryWrapper<Picking>().lambda().eq(Picking::getCode, pickingRegister.getPickingCode()).eq(Picking::getGroupCode,UserUtil.getBranchCode()).eq(Picking::getDeleted, 0));
        log.info("PDA批量拣货确认，获取拣货单信息，{}",JSONUtil.toJsonStr(picking));
        if (picking == null) {
            log.error("PDA批量拣货确认，拣货单{}不存在，请确认",pickingRegister.getPickingCode());
            throw new ServiceException("拣货单不存在，请确认");
        }
        if (picking.getStatus().equals(PickingStatusEnum.FINISH_PICK.getValue())) {
            log.error("PDA批量拣货确认，拣货单{}已完成，无法再拣货，请确认",pickingRegister.getPickingCode());
            throw new ServiceException("拣货单已完成，无法再拣货，请确认");
        }
        // 检查明细是否拣货完成了
        PickingItem pickingItem = iPickingItemService.getOne(new QueryWrapper<PickingItem>().lambda()
                .eq(PickingItem::getGroupCode,UserUtil.getBranchCode())
                .eq(PickingItem::getCode, pickingRegister.getPickingItemCode())
                .eq(PickingItem::getDeleted, 0));
        log.info("PDA批量拣货确认，获取拣货单明细，检查是否拣货完成，{}",JSONUtil.toJsonStr(pickingItem));
        BigDecimal differenceQuantity = pickingItem.getDistributionQuantity().subtract(pickingItem.getPickingQuantity())
                .subtract(pickingItem.getStockoutQuantity()).subtract(pickingRegister.getPickingQuantity());
        if (differenceQuantity.compareTo(BigDecimal.ZERO) < 0) {
            log.error("PDA批量拣货确认，拣货数量与缺货数量之和超过了计划数量，无法进行拣货确认");
            throw new ServiceException("拣货数量与缺货数量之和超过了计划数量，无法进行拣货确认");
        }
        // 占用容器
        if (StrUtil.isNotBlank(pickingRegister.getContainerBarCode())) {
            iContainerService.occupyContainerByPicking(picking.getCode(), pickingRegister.getContainerBarCode());
            //波次拣货，容器号赋值再拣货主单上
            iPickingService.update(new LambdaUpdateWrapper<Picking>().eq(Picking::getCode, pickingCode)
                    .eq(Picking::getGroupCode,groupCode)
                    .set(Picking::getContainerBarCode, pickingRegister.getContainerBarCode())
                    .set(Picking::getOccupy, NUM_ONE));
        }

        WmsTask task = iWmsTaskService.getOne(new QueryWrapper<WmsTask>().lambda().eq(WmsTask::getSourceCode, picking.getCode()).eq(WmsTask::getGroupCode,UserUtil.getBranchCode()));

        // 添加判断是否有相同数据，然后保存
        pickingRegister.setTaskCode(task.getCode());
        iPickingRegisterService.distinctSave(pickingRegister);

        //更新拣货单信息(包含拣货主单，拣货明细，拣货确认单信息)
        updatePickingInfo(pickingRegister.getPickingItemCode(),pickingRegister.getPickingQuantity(),pickingRegister.getPickingCode(),isBatch);

        // 批量操作与单条操作时，更新发货单相关信息逻辑有异
        if (isBatch) {
            iDeliveryDistributionService.update(new UpdateWrapper<DeliveryDistribution>().lambda()
                    .eq(DeliveryDistribution::getGroupCode,UserUtil.getBranchCode())
                    .eq(DeliveryDistribution::getWavePickingCode, wavePickingCode)
                    .eq(DeliveryDistribution::getOldInventoryCode, oldInventoryCode)
                    .eq(DeliveryDistribution::getDeleted, NUM_ZERO)
                    .setSql(" picking_quantity = distribution_quantity")
                    .setSql("not_recheck_quantity = picking_quantity"));
            // 更新订单明细中的拣货数量
            iDeliveryItemService.updatePickingQuantityStatusByWavePickingCode(wavePickingCode,DeliveryStatusEnum.UN_RECHECK.getValue(),UserUtil.getBranchCode());
            //更新订单的状态和数量
            iDeliveryService.updateStatusAndQuantity(wavePickingCode);


        } else {
            //  更新发货单、明细、分配单的拣货数量
            updateDeliveryInfo(picking.getDeliveryCode(), null);
        }
        //更新拣货单状态
        List<Delivery> deliveryList = iDeliveryService.list(new QueryWrapper<Delivery>().lambda().eq(Delivery::getWavePickingCode, wavePickingCode).eq(Delivery::getGroupCode,UserUtil.getBranchCode()));
        deliveryList.forEach(e-> iDeliveryService.updateDelvieryStatus(e));
        // 更新任务已完成作业量，作业状态在占用作业时就已更新，所以不需要再更新
        iWmsTaskService.update(new UpdateWrapper<WmsTask>().lambda().eq(WmsTask::getSourceCode, picking.getCode())
                .eq(WmsTask::getGroupCode,UserUtil.getBranchCode())
                .setSql(" job_quantity = job_quantity + " + pickingRegister.getPickingQuantity()));



        return switchPageVO;
    }


    @Transactional(rollbackFor = Exception.class)
    public int updateItemStatus(String pickingCode,String pickingItemCode,String unFinishRegisterCode,PdaSwitchPageVO switchPageVO){
        // 尝试根据数量判断并更新子单状态
        int finishItemFlag = iPickingItemService.updateStatusIfFinish(pickingItemCode, PickingStatusEnum.FINISH_PICK.getValue());
        if (finishItemFlag > 0) {
            // 如果子单状态更新了，说明子单的分配拣货量 = 实际拣货量 + 缺货数量，则可将用于辅助的待拣货确认数据删除
            iPickingRegisterService.remove(new QueryWrapper<PickingRegister>().lambda().eq(PickingRegister::getPickingItemCode, pickingItemCode)
                    .eq(PickingRegister::getGroupCode,UserUtil.getBranchCode())
                    .eq(PickingRegister::getStatus, PickingRegisterStatusEnum.NOT_PICK.getValue()));

            // 明细完成，可跳转到上一个页面
            switchPageVO.setToPage(NUM_ONE);
            //由于pickingRegister可能已经被删除，所以用pickingItem来代替pickingRegister来获取库位信息
            PickingItem pickingItem = iPickingItemService.getOne(new LambdaQueryWrapper<PickingItem>()
                    .eq(PickingItem::getGroupCode, UserUtil.getBranchCode())
                    .eq(PickingItem::getCode, pickingItemCode));
            // 判断当前库位上还有未拣货的信息
            List<PickingRegister> unPickingRegisters = iPickingRegisterService.list(new QueryWrapper<PickingRegister>().lambda()
                    .eq(PickingRegister::getGroupCode,UserUtil.getBranchCode())
                    .eq(PickingRegister::getPickingCode, pickingCode)
                    .eq(PickingRegister::getLocation, pickingItem.getLocation())
                    .eq(PickingRegister::getStatus, PickingRegisterStatusEnum.NOT_PICK.getValue()));
            if (IterUtil.isEmpty(unPickingRegisters)) {
                switchPageVO.setToPage(NUM_TWO);
            }


        } else {
            // 更新子单、主单状态为拣货中
            iPickingItemService.update(new UpdateWrapper<PickingItem>().lambda().eq(PickingItem::getCode, pickingItemCode).set(PickingItem::getStatus, PickingStatusEnum.PICKING.getValue()).eq(PickingItem::getGroupCode,UserUtil.getBranchCode()));
            this.iPickingService.update(new UpdateWrapper<Picking>().lambda().eq(Picking::getCode, pickingCode).set(Picking::getStatus, PickingStatusEnum.PICKING.getValue()).eq(Picking::getGroupCode,UserUtil.getBranchCode()));
        }
        return finishItemFlag;
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateFinsh(String pickingCode,String wavePickingCode,PdaSwitchPageVO switchPageVO) {
        // 再尝试触发主单拣货完成逻辑
        int finishPickingFlag = this.iPickingService.updateStatusIfFinish(pickingCode, PickingStatusEnum.FINISH_PICK.getValue());
        if (finishPickingFlag > 0) {
            //更新任务状态为已完成
            iWmsTaskService.update(new UpdateWrapper<WmsTask>().lambda().eq(WmsTask::getSourceCode, pickingCode)
                    .eq(WmsTask::getGroupCode,UserUtil.getBranchCode())
                    .set(WmsTask::getJobStatus, WmsTaskJobStatusEnum.COMPLETED.getValue()));
            // 判断拣货单及状态
            Picking picking = iPickingService.getOne(new QueryWrapper<Picking>().lambda().eq(Picking::getCode, pickingCode).eq(Picking::getGroupCode,UserUtil.getBranchCode()));
            //先将订单状态都改为“待出库”以匹配后面的业务逻辑
//            iDeliveryService.update(new UpdateWrapper<Delivery>().lambda().eq(Delivery::getWavePickingCode, wavePickingCode).set(Delivery::getStatus, DeliveryStatusEnum.UN_DELIVERY));
//            Outbound outbound = pickingConfirmationService.pickConfirmationGenOutboundInfo(picking);
            wavePickingConfirmationService.genOutboundInfoByDelivery(picking, picking.getReview());
            log.info("拣货确认：【step3】，更新订单信息");
            pickingConfirmationService.pickConfirmationUpdateDeliveryInfo(picking);
            log.info("拣货确认：【step4】，判断是否跳过复核");
            if (picking.getReview() == 0) {
                RLock ol = null;
                try {
                    ol = redissonClient.getLock(getOutConfirmLockKey(picking.getCode()));
                    if (ol.tryLock()) {
                        log.info("波次拣货【step5】：，拣货单跳过复核");
                        log.info("波次拣货【step5-1】：，自动复核");
                        outCheckService.autoReview(picking.getWavePickingCode(),UserUtil.getBranchCode());

                        log.info("波次拣货【step5-2】：自动出库");
                        outCheckService.autoOutConfirmation(picking.getWavePickingCode(),StrUtil.EMPTY, NUM_ZERO,NUM_ONE,UserUtil.getBranchCode());

                        log.info("波次拣货确认，出库单复核：【step6】，异步释放容器");
                        iPickingService.releaseContainer(picking.getWavePickingCode(),UserUtil.getBranchCode());
                    } else {
                        log.error("拣货单【{}】，拣货确认获得锁失败", picking.getCode());
                    }
                }  catch (Exception e) {
                    log.error(StrConsts.CATCH_MESSAGE, e);
                    throw new ServiceException(e.getMessage());
                } finally {
                    try {
                        if (null != ol && ol.isLocked()) {
                            ol.unlock();
                        }
                    } catch (Exception e) {
                        log.error("出库确认释放锁失败！！", e);
                    }
                }
            }

            // 单据完成，可跳转到拣货列表页面
            switchPageVO.setToPage(NUM_THREE);
        } else {
            // 更新主单状态为拣货中
            this.iPickingService.update(new UpdateWrapper<Picking>().lambda().eq(Picking::getCode, pickingCode).eq(Picking::getGroupCode,UserUtil.getBranchCode()).set(Picking::getStatus, PickingStatusEnum.PICKING.getValue()));
        }

    }







    @Transactional(rollbackFor = {Exception.class})
    public void updatePickingInfo(String pickingItemCode,BigDecimal pickingQuantity,String pickingCode,boolean isBatch) {
        // 更新拣货确认表中那条未拣货数据的拣货数量
        //如果时生成波次的拣货单，拣货数量初始值为0，所已不对其进行做差操作，防止出现负数
        if (isBatch) {
            iPickingRegisterService.update(new UpdateWrapper<PickingRegister>().lambda().eq(PickingRegister::getPickingItemCode, pickingItemCode)
                    .eq(PickingRegister::getGroupCode,UserUtil.getBranchCode())
                    .eq(PickingRegister::getDeleted, 0).eq(PickingRegister::getStatus, PickingRegisterStatusEnum.NOT_PICK.getValue())
                    .setSql(" not_picking_quantity = not_picking_quantity - " + pickingQuantity));
        } else {
            iPickingRegisterService.update(new UpdateWrapper<PickingRegister>().lambda().eq(PickingRegister::getPickingItemCode, pickingItemCode)
                    .eq(PickingRegister::getGroupCode,UserUtil.getBranchCode())
                    .eq(PickingRegister::getDeleted, 0).eq(PickingRegister::getStatus, PickingRegisterStatusEnum.NOT_PICK.getValue())
                    .setSql(" not_picking_quantity = not_picking_quantity - " + pickingQuantity)
                    .setSql(" picking_quantity = picking_quantity - " + pickingQuantity));
        }

        // 更新明细拣货数量
        iPickingItemService.update(new UpdateWrapper<PickingItem>().lambda().eq(PickingItem::getCode, pickingItemCode)
                .eq(PickingItem::getGroupCode,UserUtil.getBranchCode())
                .setSql(" picking_quantity = picking_quantity + " + pickingQuantity));
        // 更新主单拣货数量、待拣货数量
        this.iPickingService.update(new UpdateWrapper<Picking>().lambda().eq(Picking::getCode, pickingCode)
                .eq(Picking::getGroupCode,UserUtil.getBranchCode())
                .setSql(" picking_quantity = picking_quantity + " + pickingQuantity)
                .setSql(" not_picking_quantity = not_picking_quantity - " + pickingQuantity));
    }

    /**
     * 更新发货模块各表的拣货数量
     *
     * @param deliveryCode
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public Result updateDeliveryInfo(String deliveryCode, String wavePickingCode) {
        String groupCode = UserUtil.getBranchCode();
        // 更新分配单拣货数量
        iDeliveryDistributionService.updatePickingQuantityForCheck(deliveryCode,groupCode);
        // 更新订单明细中的拣货数量
        iDeliveryItemService.updatePickingQuantityForCheck(deliveryCode,groupCode);
        // 更新订单中的总拣货数量
        iDeliveryService.updatePickNumByDistributionData(deliveryCode);

        // 更新发货单状态
        if (StrUtil.isEmpty(wavePickingCode)) {
            iDeliveryService.updateDeliveryStatusIfEmptyDistribution(deliveryCode,groupCode);
        } else {
            //波次号wavePickingCode不为空时，更新发货单的状态为待复核
            iDeliveryService.updateStatusByWavePickingCode(wavePickingCode,DeliveryStatusEnum.UN_RECHECK.getValue(),groupCode);
            iDeliveryItemService.update(new UpdateWrapper<DeliveryItem>().lambda().eq(DeliveryItem::getWavePickingCode, wavePickingCode)
                    .eq(DeliveryItem::getGroupCode,UserUtil.getBranchCode())
                    .set(DeliveryItem::getStatus, DeliveryStatusEnum.UN_RECHECK.getValue()));
        }
        return Result.ok();
    }

    /**
     * 批量拣货登记（按库位）
     * @author liuxr
     * @date 2021/5/29 11:22
     */
    @Override
    public PdaSwitchPageVO batchCheckByLocation(String taskCode, BigDecimal pickingQuantity, String goodsBarCode, String pn,String location){
        String groupCode = UserUtil.getBranchCode();
        //检验参数是否为空
       validateParams(taskCode, pickingQuantity, goodsBarCode, pn,location);
        WmsTask task = this.iWmsTaskService.getOne(new LambdaQueryWrapper<WmsTask>()
                .eq(WmsTask::getCode, taskCode)
                .eq(WmsTask::getGroupCode,groupCode)
        );
        String pickingCode = task.getSourceCode();
        //pn码校验
        iPickingService.validatePnInfo(pickingCode,goodsBarCode,pn,groupCode);
        List<PickingRegister> pickingRegisters = iPickingRegisterService.list(new LambdaQueryWrapper<PickingRegister>()
                .eq(PickingRegister::getLocation,location)
                .eq(PickingRegister::getPickingCode, pickingCode)
                .eq(PickingRegister::getGoodsBarCode, goodsBarCode)
                .eq(PickingRegister::getGroupCode,groupCode)
                .eq(PickingRegister::getStatus,PickingStatusEnum.NOT_PICK.getValue()));
        if(IterUtil.isEmpty(pickingRegisters)) {
            throw  new ServiceException("拣货登记信息不能为空");
        }

        //剩余的拣货数量
        BigDecimal remainingPickingQuantity = pickingQuantity;
        PdaSwitchPageVO pdaSwitchPageVO = new PdaSwitchPageVO();
        for (PickingRegister register : pickingRegisters) {
            BigDecimal planPickingQuantity ;
            //分配拣货数量
            if (remainingPickingQuantity.compareTo(register.getDistributionQuantity()) > 0) {
                planPickingQuantity = register.getDistributionQuantity();
                remainingPickingQuantity = remainingPickingQuantity.subtract(register.getDistributionQuantity());
            } else {
                planPickingQuantity = remainingPickingQuantity;
            }
            pdaSwitchPageVO = batchRegister(pickingCode, register.getPickingItemCode(), register.getCode(), planPickingQuantity, StrUtil.EMPTY);
        }
        return pdaSwitchPageVO;
    }

    private void  validateParams(String taskCode, BigDecimal pickingQuantity, String goodsBarCode, String pn,String location){
        if (StrUtil.isEmpty(taskCode)) {
            throw new ServiceException("任务号不能为空");
        }
        if (null == pickingQuantity || pickingQuantity.compareTo(BigDecimal.ZERO) < 1) {
            throw new ServiceException("拣货数量需要大于0");
        }
        if (StrUtil.isEmpty(goodsBarCode)) {
            throw new ServiceException("商品条码不能为空");
        }
        if (StrUtil.isEmpty(pn)) {
            throw new ServiceException("商品pn码不能为空");
        }
        if (StrUtil.isEmpty(location)) {
            throw new ServiceException("库位code不能为空");
        }
    }
    /**
     * 拣货确认分布式锁key
     *
     * @param code 拣货单号
     * @return
     */
    private String getPickingCheckLockKey(String code) {
        return String.format("picking-check-lock-%s", code);
    }

    /**
     * 拣货确认分布式锁key
     *
     * @param code 拣货单号
     * @return
     */
    private String getOutConfirmLockKey(String code) {
        return String.format("outConfirm-lock-%s", code);
    }
}
